package com.egs.witzbackend.controller;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.StringTokenizer;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;
import javax.servlet.http.*;

import com.egs.witzbackend.domain.GameMatch;
import com.egs.witzbackend.domain.Move;
import com.egs.witzbackend.domain.Player;
import com.egs.witzbackend.game.CounterService;
import com.egs.witzbackend.game.GameService;
import com.egs.witzbackend.game.PlayerService;
import org.apache.commons.codec.binary.Base64;

@SuppressWarnings("serial")
public class WitzBackendServlet extends HttpServlet {
	// Factory to get persistence manager object later
	private static final PersistenceManagerFactory PMF = JDOHelper.getPersistenceManagerFactory("transactions-optional");
	private static final GameService gameService = new GameService(PMF);
	private static final PlayerService playerService = new PlayerService(PMF);
	private static final CounterService counterService = new CounterService(PMF);
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		resp.setContentType("text/plain");
		
		String gameId = (String) req.getParameter("gameId");
		if (gameId == null) {
			gameId = "spirits";
		}
		String player1Id = (String) req.getParameter("player1Id");
		if (player1Id == null) {
			player1Id = "p1";
		}
		String player2Id = (String) req.getParameter("player2Id");
		if (player2Id == null) {
			player2Id = "p2";
		}
		
		Player player1 = null;
		Player player2 = null;
		GameMatch gameMatch = null;
		if (player1Id != null && player2Id != null) {
			player1 = playerService.GetPlayer(player1Id);
			if (player1 == null) {
				player1 = playerService.RegisterPlayer(player1Id, "");
			}
			player2 = playerService.GetPlayer(player2Id);
			if (player2 == null) {
				player2 = playerService.RegisterPlayer(player2Id, "");
			}
			gameMatch = gameService.GetGameMatch(gameId, player1, player2);
			if (gameMatch == null) {
				gameMatch = gameService.RegisterGameMatch(gameId, player1, player2, null);
			}
		}
		
		String requestType = (String) req.getParameter("gameRequestType");
		if (requestType != null && requestType.equals("retrieveMove")) {
			Move move = gameService.GetMove(gameMatch);
			if (move != null) {
				String playerId = move.getPlayerId();
				String startX = move.getStartX();
				String startY = move.getStartY();
				String endX = move.getEndX();
				String endY = move.getEndY();
				String boardBeforeMove = move.getBoardBeforeMove();
				String boardAfterMove = move.getBoardAfterMove();
				String hpP1BeforeMove = move.getHpP1BeforeMove();
				String hpP2BeforeMove = move.getHpP2BeforeMove();
				String hpP1AfterMove = move.getHpP1AfterMove();
				String hpP2AfterMove = move.getHpP2AfterMove();
				resp.getWriter().println(playerId + "," + startX + "," + startY + "," + endX + "," + endY + "," + boardBeforeMove + "," + boardAfterMove + "," + hpP1BeforeMove + "," + hpP2BeforeMove + "," + hpP1AfterMove + "," + hpP2AfterMove);
			} else {
				resp.getWriter().println("0,0,0,0,0");
			}
		} else if (requestType != null && requestType.equals("submitMove")) {
			String playerId = (String) req.getParameter("playerId");
			String startX = (String) req.getParameter("startX");
			String startY = (String) req.getParameter("startY");
			String endX = (String) req.getParameter("endX");
			String endY = (String) req.getParameter("endY");
			String boardBeforeMove = req.getParameter("boardBeforeMove");
			String boardAfterMove = req.getParameter("boardAfterMove");
			String hpP1BeforeMove = req.getParameter("hpP1BeforeMove");
			String hpP2BeforeMove = req.getParameter("hpP2BeforeMove");
			String hpP1AfterMove = req.getParameter("hpP1AfterMove");
			String hpP2AfterMove = req.getParameter("hpP2AfterMove");
			gameService.RegisterMove(gameMatch, playerId, startX, startY, endX, endY, boardBeforeMove, boardAfterMove, hpP1BeforeMove, hpP2BeforeMove, hpP1AfterMove, hpP2AfterMove);
			resp.getWriter().println(playerId + "," + startX + "," + startY + "," + endX + "," + endY);
		}
	}
	
	public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		BufferedReader reader = req.getReader();
		String line = reader.readLine();
		if (line != null) {
			//Parse Players
			StringTokenizer lineTokenizer = new StringTokenizer(line,":");
			String paramType = lineTokenizer.nextToken();
			String player1Id = null;
			String player2Id = null;
			if (lineTokenizer.hasMoreTokens() && paramType != null && paramType.equals("players")) {
				String param = lineTokenizer.nextToken();
				if (param != null) {
					StringTokenizer paramTokenizer = new StringTokenizer(param, ",");
					int player = Integer.parseInt(paramTokenizer.nextToken());
					if (player == 0) {
						player1Id = paramTokenizer.nextToken();
					} else {
						player2Id = paramTokenizer.nextToken();
					}
					
					player = Integer.parseInt(paramTokenizer.nextToken());
					if (player == 0) {
						player1Id = paramTokenizer.nextToken();
					} else {
						player2Id = paramTokenizer.nextToken();
					}
				}
				line = reader.readLine();
			}
			
			Player player1 = null;
			Player player2 = null;
			GameMatch gameMatch = null;
			if (player1Id != null && player2Id != null) {
				player1 = playerService.GetPlayer(player1Id);
				player2 = playerService.GetPlayer(player2Id);
				
				
				if (player1 != null && player2 != null) {
					gameMatch = gameService.GetGameMatch("witz", player1, player2);
					
					if (gameMatch == null) {
						gameMatch = gameService.RegisterGameMatch("witz", player1, player2, "");
					}
				}
			}
			
			if (line != null) {
				if (gameMatch != null && line.equals("retrieveTurn")) {
					resp.getWriter().print(gameMatch.getGameString().getValue());
				} else if (gameMatch != null && line.equals("submitTurn")) {
					String gameString = "";
					while ((line = reader.readLine()) != null) {
						gameString += line + "\n";
					}
					gameService.RegisterGameString(gameMatch, gameString);
					
					String playerId = null;
					if (gameMatch.getGameString() != null) {
						String gameMatchString = gameMatch.getGameString().getValue();
						if (gameMatchString != null && !gameMatchString.equals("")) {
							StringTokenizer gameTokenizer = new StringTokenizer(gameMatchString, "\n");
							String gameLine;
							while ((gameLine = gameTokenizer.nextToken()) != null) {
								StringTokenizer gameLineTokenizer = new StringTokenizer(gameLine,":");
								String gameParamType = gameLineTokenizer.nextToken();
								if (gameParamType.equals("player")) {
									String playerString = gameLineTokenizer.nextToken();
									StringTokenizer playerIdTokenizer = new StringTokenizer(playerString, ",");
									playerIdTokenizer.nextToken(); // Read passed the playerOrdinal
									playerId = playerIdTokenizer.nextToken();
									break;
								}
							}
						}
					}
					
					String pushId = null;
					Player player = null;
					if (player1.getPlayerId().equals(playerId)) {
						pushId = player2.getPushId();
						player = player2;
					} else if (player2.getPlayerId().equals(playerId)) {
						pushId = player1.getPushId();
						player = player2;
					}
					
					if (pushId != null && player != null && !pushId.equals("")) {
						sendWitzTurnPush(pushId, player);
					}
					
				} else if (gameMatch != null && line.equals("submitNudge")) {
					//Parse Player
					String playerId = null;
					line = reader.readLine();
					lineTokenizer = new StringTokenizer(line, ":");
					paramType = lineTokenizer.nextToken();
					if (lineTokenizer.hasMoreTokens() && paramType != null && paramType.equals("player")) {
						playerId = lineTokenizer.nextToken();
					}
					
					String pushId = null;
					Player player = null;
					if (player1.getPlayerId().equals(playerId)) {
						pushId = player1.getPushId();
						player = player2;
					} else if (player2.getPlayerId().equals(playerId)) {
						pushId = player2.getPushId();
						player = player1;
					}
					
					if (pushId != null && player != null && !pushId.equals("")) {
						sendWitzTurnPush(pushId, player);
					}
				} else if (gameMatch != null && line.equals("eraseGame")) {
					gameService.DeleteGameMatch(gameMatch);
				} else if (line.equals("retrieveGameMatches")) {
					ArrayList<GameMatch> gameMatches = new ArrayList<GameMatch>();
					
					//Parse Player
					String playerId = null;
					line = reader.readLine();
					lineTokenizer = new StringTokenizer(line, ":");
					paramType = lineTokenizer.nextToken();
					if (lineTokenizer.hasMoreTokens() && paramType != null && paramType.equals("player")) {
						playerId = lineTokenizer.nextToken();
					}
					
					if (playerId != null) {
						Player player = playerService.GetPlayer(playerId);
						if (player != null) {
						gameMatches = gameService.GetGameMatches("witz", player);
							for (int i = 0; i < gameMatches.size(); i++) {
								GameMatch match = gameMatches.get(i);
								String scoreString = null;
								String playerString = null;
								if (match.getGameString() != null) {
									String gameString = match.getGameString().getValue();
									if (gameString != null && !gameString.equals("")) {
										StringTokenizer gameTokenizer = new StringTokenizer(gameString, "\n");
										String gameLine;
										while ((gameLine = gameTokenizer.nextToken()) != null) {
											StringTokenizer gameLineTokenizer = new StringTokenizer(gameLine,":");
											String gameParamType = gameLineTokenizer.nextToken();
											if (gameParamType.equals("score")) {
												scoreString = gameLine;
											} else if (gameParamType.equals("player")) {
												playerString = gameLine;
											}
											
											if (scoreString != null && playerString != null) {
												break;
											}
										}
									}
								}
								if (scoreString != null && playerString != null) {
									String playersString = "game\nplayers:0," + gameMatches.get(i).getPlayer1Id() + ",1," + gameMatches.get(i).getPlayer2Id();
									resp.getWriter().println(playersString);
									resp.getWriter().println(playerString);
									resp.getWriter().println(scoreString);
								}
							}
						}
					}
				} else if (line.equals("registerPlayer")) {
					
					Integer count = counterService.getMainCount();
					counterService.IncrementMainCount();
					String playerId = "" + count;
					Player player = playerService.GetPlayer(playerId);
					if (player == null) {
						String pushId ="";
						
						//Parse pushId
						line = reader.readLine();
						if (line != null) {
							lineTokenizer = new StringTokenizer(line, ":");
							paramType = lineTokenizer.nextToken();
							if (lineTokenizer.hasMoreTokens() && paramType != null && paramType.equals("pushId")) {
								pushId = lineTokenizer.nextToken();
							}
						}
						
						player = playerService.RegisterPlayer(playerId, pushId);
					}
					
					if (player != null) {
						resp.getWriter().println("player:" + playerId);
					}
				} else if (line.equals("retrievePlayers")) {
					ArrayList<String> playerIds = playerService.GetPlayerIds();
					if (!playerIds.isEmpty()) {
						resp.getWriter().print("players:");
						for (int i = 0; i < playerIds.size(); i++) {
							if (i == 0) {
								resp.getWriter().print(playerIds.get(i));
							} else {
								resp.getWriter().print("," + playerIds.get(i));
							}
						}
					}
				}
			}
		}
	}

	private void sendWitzTurnPush(String deviceToken, Player player) {
		String appKey = "3Z3XWtJnQhmeILBUf0ACRQ";//"WBPdMd_BSG-F-xKsrRcwRg";
		String appMasterSecret = "l7WrTqbcTH-vG5Qd5jUoXQ";//"GUG8ECzEQSKpRoqS-AyNgA";

		String authString = appKey + ":" + appMasterSecret;
		String authStringBase64 = Base64.encodeBase64String(authString.getBytes());
		authStringBase64 = authStringBase64.trim();
		try {
			URL url = new URL("https://go.urbanairship.com/api/push/");
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			connection.setRequestMethod("POST");
			connection.setDoOutput(true);
			
			connection.setRequestProperty("Content-type", "application/json");
			connection.setRequestProperty("Authorization", "Basic " + authStringBase64);
			
			//ArrayList<GameMatch> matches = gameService.GetGameMatches("witz", player);
			int numMatches = 0;
			//if (matches != null) {
			//	numMatches = matches.size();
			//}
			numMatches = 1;
			
			String jsonBodyString = "{\"aps\": {\"badge\": " + numMatches + ", \"alert\": \"Your Turn!\", \"sound\": \"default\"}, \"device_tokens\": [\"" + deviceToken + "\"]}";

			OutputStreamWriter osw = new OutputStreamWriter(connection.getOutputStream());
			osw.write(jsonBodyString);
			osw.close();
			int responseCode = connection.getResponseCode();
			// Add your code to check the response code here
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		

		

		

		
	}
}
